package org.paradigmshift.timelapse.daos

import org.paradigmshift.timelapse.domain.Issue
import org.paradigmshift.timelapse.rest.JsonRestConnection
import org.paradigmshift.timelapse.serializers.IssueSerializer
import org.paradigmshift.timelapse.TimeLapsePreferences

import net.liftweb.json.compact
import net.liftweb.json.render
import net.liftweb.json.DefaultFormats
import net.liftweb.json.Extraction
import net.liftweb.json.JsonParser

object IssueDao {
  
  private implicit val formats = DefaultFormats + new IssueSerializer
  private def toJson( issue:Issue ):String = compact( render( Extraction.decompose( issue ) ) )
  
  def create( issue:Issue ) {
    JsonRestConnection.post( "/issue", toJson( issue ) )
  }
  
  def findByKey( key:String ):Option[Issue] = {
    for {
      jsonString <- JsonRestConnection.get( "/issue/" + key, Map( "fields" -> "reporter,assignee,summary,description,priority" ) )
    }
    yield JsonParser.parse( jsonString ).extract[Issue]
  }
  
  def findByFullText( arg:String ):List[Issue] = {
    
    val query = "text ~ \"" + arg + "\""
    findByJson( Map[String,Any] ( "jql" -> query ) )
  }
  
  def findByJson( jsonMap:Map[String,Any] ):List[Issue] = {
    if ( !jsonMap.isEmpty && jsonMap.contains( "jql" ) ) {
      val map = jsonMap ++
        Map[String,Any] ( "fields" -> Array( "reporter", "assignee", "summary", "description", "priority" ) ) ++
        (if ( !jsonMap.contains( "startAt" ) ) Map[String,Any] ( "startAt" -> 0 ) else Nil) ++
        (if ( !jsonMap.contains( "maxResults" ) ) Map[String,Any] ( "maxResults" -> TimeLapsePreferences.getResultSetSize ) else Nil)
      
      val jsonQuery = compact( render( Extraction.decompose( map ) ) )
      (for {
        jsonString <- JsonRestConnection.post( "/search", jsonQuery )
      }
      yield {
        val json = JsonParser.parse( jsonString )
        (json \ "issues").children.map( jsonIssue => jsonIssue.extract[Issue] )
      }).getOrElse( Nil )
    }
    else Nil
  }
  
  def update( issue:Issue ) =
    for { key <- issue.key } yield { JsonRestConnection.put( "/issue/" + key, toJson( issue ) ) }
  
  def delete( issue:Issue ) =
    for { key <- issue.key } yield { JsonRestConnection.delete( "/issue/" + key ) }
}